package ogmios.dialogs;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.border.*;
import java.io.*;
import java.util.regex.*;
import java.util.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import ogmios.core.*;
/**
 * A menu for displaying all files in a directory and subdirectories. 
 */
public class FolderNavigator extends JFrame
{
  private final JTree tree;
  private final DefaultTreeModel treeModel;
  private final DefaultMutableTreeNode root;
  private final FindAndReplaceDialog findAndReplaceDialog;
  private ArticleNode activeNode;
  private JTextField searchField;
  private JList resultsBox;
  private DefaultListModel results;
  private JLabel title;
  private JTextArea text;
  private Pattern search;

  public static FolderNavigator showDialog(String navigateDirectory)
  {
    FolderNavigator fn = new FolderNavigator(navigateDirectory);
    fn.setVisible(true);

    return fn;
  }

  private FolderNavigator(String navigateDirectory)
  {
    setTitle(navigateDirectory);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    findAndReplaceDialog = new FindAndReplaceDialog();
    File f = new File(navigateDirectory);

    tree = new JTree(treeModel = new DefaultTreeModel(root = new DefaultMutableTreeNode(navigateDirectory)));
    tree.setCellRenderer(
      new DefaultTreeCellRenderer()
    {
      public Component getTreeCellRendererComponent(JTree tree, Object val,
          boolean selected,
          boolean expanded, boolean leaf,
          int row, boolean hasFocus)
      {
        setIcon(leaf ?
                val instanceof ArticleNode ?
                getLeafIcon() :
                getClosedIcon() :
                expanded ? getOpenIcon() :
                getClosedIcon()
               );

        setText(val.toString());
        this.selected = selected;
        this.hasFocus = hasFocus;
        setHorizontalAlignment(LEFT);
        setOpaque(false);
        setVerticalAlignment(CENTER);
        setEnabled(true);
        super.setFont(UIManager.getFont("Tree.font"));

        if (selected)
        {
          super.setBackground(getBackgroundSelectionColor());
          setForeground(getTextSelectionColor());

          if (hasFocus)
            setBorderSelectionColor(UIManager.getLookAndFeelDefaults().getColor("Tree.selectionBorderColor"));
          else
            setBorderSelectionColor(null);
        }
        else
        {
          super.setBackground(getBackgroundNonSelectionColor());
          setForeground(getTextNonSelectionColor());
          setBorderSelectionColor(null);
        }

        return this;
      }
    }
    );
    tree.addMouseListener(
      new MouseAdapter()
    {
      public void mouseClicked(MouseEvent e)
      {
        if (e.getClickCount() == 2)
        {
          TreePath obj = tree.getPathForLocation(e.getX(), e.getY());
          if (obj != null)
          {
            DefaultMutableTreeNode o = (DefaultMutableTreeNode)obj.getLastPathComponent();
            if (o instanceof ArticleNode)
              openArticle((ArticleNode)o);
          }
        }
      }
    }
    );
    tree.addKeyListener(
      new KeyAdapter()
    {
      public void keyPressed(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {
          TreePath path = tree.getSelectionPath();
          if (path != null)
          {
            DefaultMutableTreeNode n = (DefaultMutableTreeNode)path.getLastPathComponent();
            if (n instanceof ArticleNode)
              openArticle((ArticleNode) n);
            else if (tree.isExpanded(path))
              tree.collapsePath(path);
            else
              tree.expandPath(path);


          }
        }
      }
    }
    );
    text = new JTextArea();
    text.setName("text");
    if (f.isDirectory())
    {
      addSubFiles(f, root);

    }
    else
    {
      text.setText("There are no files to navigate!");
    }
    JTabbedPane jtp = new JTabbedPane();
    jtp.add(new JScrollPane(tree), "Contents");
    JPanel panel = new JPanel();
    panel.setLayout(new BorderLayout());
    JPanel subPanel = new JPanel();
    subPanel.setLayout(new BorderLayout());
    JButton search = new JButton("Search");
    searchField = (JTextField)OgmiosUtilities.undoable(new JTextField());
    searchField.addKeyListener(
      new KeyAdapter()
    {
      public void keyPressed(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
          searchFiles();

      }
    }
    );
    search.addActionListener(
      new ActionListener()
    {

      public void actionPerformed(ActionEvent e)
      {
        searchFiles();
      }
    }
    );
    subPanel.add(searchField);
    subPanel.add(search, BorderLayout.EAST);

    panel.add(subPanel, BorderLayout.NORTH);
    resultsBox = new JList(results = new DefaultListModel());
    resultsBox.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    resultsBox.addMouseListener(
      new MouseAdapter()
    {
      public void mouseClicked(MouseEvent e)
      {
        if (e.getClickCount() == 2)
        {
          ArticleNode article;
          expandToNode(article = (ArticleNode)resultsBox.getSelectedValue());
          openArticle(article);
        }
      }
    }
    );
    resultsBox.addKeyListener(
      new KeyAdapter()
    {
      public void keyPressed(KeyEvent e)
      {
        if (e.getKeyCode() == KeyEvent.VK_ENTER)
        {
          Object o = resultsBox.getSelectedValue();
          if (o != null)
          {
            ArticleNode article = (ArticleNode)o;
            expandToNode(article);
            openArticle(article);
          }
        }
      }
    }
    );
    panel.add(new JScrollPane(resultsBox));
    jtp.add(panel, "Search");
    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new BorderLayout());

    text.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "find");
    text.getActionMap().put("find",
                            new AbstractAction()
    {
      public void actionPerformed(ActionEvent e)
      {

        if (text.isFocusOwner() == false)
          text.grabFocus();
        findAndReplaceDialog.showDialog(FolderNavigator.this);

      }
    }
                           );

    mainPanel.add(new JScrollPane(text));
    mainPanel.add(title = new JLabel("Unoccupied", JLabel.CENTER), BorderLayout.NORTH);
    title.setFont(title.getFont().deriveFont(title.getFont().getSize() * 1.5f));
    text.setEditable(false);
    JSplitPane jsp;
    getContentPane().add(jsp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, false, jtp, mainPanel));

    pack();

    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    setSize((int)(screenSize.width / 1.5), (int)(screenSize.height / 1.25));
//setSize(jtp.getWidth() * 3, getHeight() + 175);


  }
  public void expandToNode(ArticleNode article)
  {
    TreePath selectedPath;
    tree.scrollPathToVisible(selectedPath = new TreePath(treeModel.getPathToRoot(article)));
    tree.setSelectionPath(selectedPath);
  }

  public void openArticle(ArticleNode article)
  {
    text.setText(article.text);
    text.setSelectionStart(0);
    text.setSelectionEnd(0);
    title.setText(article.title);
  }
  private void addSubFiles(File f, DefaultMutableTreeNode parent)
  {
    for (File subFile : f.listFiles())
      if (!subFile.isHidden())
        if (subFile.isDirectory())
        {
          DefaultMutableTreeNode node = new DefaultMutableTreeNode(subFile.getName());
          parent.add(node);
          addSubFiles(subFile, node);
        }
        else if (subFile.canRead())
        {
          String n;
          int i;
          n = subFile.getName();
          if ( (i = n.lastIndexOf(".")) != -1)
            n = n.substring(0, i);
          parent.add(new ArticleNode(n, OgmiosUtilities.fileContents(subFile)));
        }
  }


  public void searchFiles()
  {
    results.clear();
    String text;
    if ((text=searchField.getText()).length() > 0)
    {
       StringBuilder regex = new StringBuilder();
       java.util.List<String> tokens = CommandManager.splitCommandLine(text.toLowerCase());
       if (tokens == null)
        return;
       for (String token : tokens)
       {
        regex.append("(");
        regex.append(Pattern.quote(token));
        regex.append(")|");
        }
      search = Pattern.compile(regex.length() == 0 ? "" : regex.substring(0, regex.length() - 1));
      checkDirectory(root);
    }
  }
  public void checkDirectory(DefaultMutableTreeNode directory)
  {
    for ( Enumeration e = directory.children(); e.hasMoreElements(); )
    {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode)e.nextElement();
      if (node instanceof ArticleNode)
      {
        ArticleNode article = (ArticleNode) node;
        if (search.matcher(article.title.toLowerCase()).find())
        {
          results.addElement(article);
          continue;
        }
        if (search.matcher(article.text.toLowerCase()).find())
        {
          results.addElement(article);
          continue;
        }
      }
      else
      {
        checkDirectory(node);
      }
    }

  }

  public static class ArticleNode extends DefaultMutableTreeNode
  {
    public final String text;
    public final String title;

    public ArticleNode(String newTitle, String newText)
    {
      title = newTitle;
      text = newText;
    }

    public String toString()
    {
      return title;
    }

  }

}
